﻿using System;
using BoatNGoat.Logic.Map.Generator;

namespace BoatNGoat.Logic.Map
{
    class Map : IMap
    {
        public static IMap CreateMapFromHeightFunction(IHeightFunction heightFunction, int width, int height)
        {
            Tile[,] tiles = new Tile[width, height];
            for (int x = 0; x < width; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    double z = heightFunction.Z(x, y);

                    Tile tile = Tile.Mountain;
                    if (z < 0.8) { tile = Tile.Forest; }
                    if (z < 0.3) { tile = Tile.Sand;   }
                    if (z < 0.1) { tile = Tile.Water;  }

                    tiles[x, y] = tile;
                }
            }

            return new Map(tiles);
        }


        // Private constructor. Maps are made via CreateMapFromHeightFunction
        private Map(Tile[,] tiles)
        {
            Tiles = tiles;
        }

        public Tile[,] Tiles
        {
            get;
            private set;
        }

        public int Width
        {
            get 
            {
                return Tiles.GetLength(0);
            }
        }

        public int Height
        {
            get
            {
                return Tiles.GetLength(1);
            }
        }

        private MapBox2 ClippedBox(MapBox2 box)
        {
            return new MapBox2()
                {
                    Bottom = Math.Max(box.Bottom, 0),
                    Top = Math.Min(box.Top, Height),
                    Left = Math.Max(box.Left, 0),
                    Right = Math.Min(box.Right, Width)
                };
        }

        public MapCollisionData Collide(MapBox2 hitbox)
        {
            hitbox = ClippedBox(hitbox);
            MapCollisionData data = new MapCollisionData();

            // foreach tile in the box, etc.
            // This is awful. Need to make a Tile class at some point.

            // Don't look at meeeeeee

            for (int x = (int)Math.Floor(hitbox.Left); x < Math.Ceiling(hitbox.Right); ++x)
            {
                for (int y = (int)Math.Floor(hitbox.Bottom); y < Math.Ceiling(hitbox.Top); ++y)
                {
                    Tile tile = Tiles[x,y];

                    switch (tile)
                    {
                        case Tile.Water: 
                            data.Water = true; break;
                        case Tile.Forest: 
                            data.Land = true; break;
                        case Tile.Sand: 
                            data.Land = true; break;
                        case Tile.Mountain: 
                            data.Blocked = true; break;
                    }
                }
            }

            return data;
        }
    }
}
